package com.songlanyun.modules.order.service.impl.createorder;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.enums.GoodsConstant;
import com.songlanyun.common.enums.IntegralConstant;
import com.songlanyun.common.enums.OrderConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.StrUtil;
import com.songlanyun.common.utils.custom.MathUtils;
import com.songlanyun.modules.account.entity.UserIdentityAssetEntity;
import com.songlanyun.modules.account.service.UserIdentityAssetService;
import com.songlanyun.modules.exception.GoodsExceptionEnum;
import com.songlanyun.modules.exception.MemberException;
import com.songlanyun.modules.goods.entity.Goods;
import com.songlanyun.modules.goods.entity.GoodsSku;
import com.songlanyun.modules.goods.service.GoodsService;
import com.songlanyun.modules.goods.service.GoodsSkuService;
import com.songlanyun.modules.integralrecord.service.IntegralRecordService;
import com.songlanyun.modules.inter.ISaleEntity;
import com.songlanyun.modules.memberbill.entity.GiveBalanceDTO;
import com.songlanyun.modules.order.dao.OrderDao;
import com.songlanyun.modules.order.entity.Order;
import com.songlanyun.modules.order.model.dto.SubmitChildOrderDTO;
import com.songlanyun.modules.order.model.dto.SubmitOrderDTO;
import com.songlanyun.modules.order.model.dto.SubmitShopOrderDTO;
import com.songlanyun.modules.order.model.vo.SubmitChildOrderVo;
import com.songlanyun.modules.order.model.vo.SubmitOrderReceiptVo;
import com.songlanyun.modules.order.model.vo.SubmitOrderVo;
import com.songlanyun.modules.order.model.vo.SubmitShopOrderVo;
import com.songlanyun.modules.order.service.ChildOrderService;
import com.songlanyun.modules.order.service.CreateOrderService;
import com.songlanyun.modules.order.service.OrderService;
import com.songlanyun.modules.payorder.entity.PayOrder;
import com.songlanyun.modules.payorder.service.PayOrderService;
import com.songlanyun.modules.saleconfig.service.SaleConfigService;
import com.songlanyun.modules.singlegoods.entity.ProductSingleGoodsEntity;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 积分商品订单构单与下单
 */
@Service("pointGoodsCreateOrderService")
public class PointGoodsCreateOrderServiceImpl extends ServiceImpl<OrderDao, Order> implements CreateOrderService {

    @Resource(name="createOrderService")
    private CreateOrderService createOrderService;

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private GoodsSkuService goodsSkuService;
    @Autowired
    private PayOrderService payOrderService;

    @Autowired
    private ChildOrderService childOrderService;

    @Autowired
    private SaleConfigService saleConfigService;


    @Autowired
    private UserIdentityAssetService  userIdentityAssetService;


    @Autowired
    private IntegralRecordService integralRecordService;

    /**
     * 构建下单页数据
     *
     * @param userId
     * @param dto
     * @return
     */
    @Override
    public SubmitOrderVo buildSubmitOrder(Long userId, SubmitOrderDTO dto) {
        validateGoods(userId,dto);
        SubmitOrderVo vo = initSubmitOrderVo(userId, dto);
        List<SubmitShopOrderVo> shopOrderVoList = commonOrderBuild(userId, vo, dto);

        BigDecimal totalMoney = MathUtils.setScale(shopOrderVoList.stream().mapToDouble(c -> c.getTotalAmount().doubleValue()).sum());
        //BigDecimal totalReducedMoney = MathUtils.setScale(shopOrderVoList.stream().mapToDouble(c -> c.getTotalReduced().doubleValue()).sum());
        BigDecimal totalReducedMoney = BigDecimal.ZERO;
        BigDecimal totalPoint = MathUtils.setScale(shopOrderVoList.stream().mapToDouble(c -> c.getTotalPoint().doubleValue()).sum());
        UserIdentityAssetEntity asset = userIdentityAssetService.getById(userId, true);
        if(!asset.isEnoughPoint(totalPoint))
        {
            throw new RRException(MemberException.LACK_OF_INTEGRAL);
        }
        vo.setShopOrders(shopOrderVoList);
        vo.setAreaFeature(GoodsConstant.AreaFeature.GENERAL);
        vo.setTotalMoney(totalMoney);
        vo.setTotalReduced(totalReducedMoney);
        vo.setPointGoods(true);
        vo.setTotalPoint(totalPoint);
        vo.setPointEnough(asset.getIntegralAble().compareTo(vo.getTotalPoint()) >= 0);

        return vo;
    }



    /**
     * 会员下单服务
     *
     * @param userId
     * @param dto
     * @return
     */

    @Override
    public PayOrder createPayOrder(Long userId, SubmitOrderDTO dto) {
        /**
         * 校验普通订单
         */
        validateGoods(userId, dto);
        /**
         * 构建下单数据
         */
        SubmitOrderVo submitOrderVo = buildSubmitOrder(userId, dto);
        /**
         *
         * 提取商品图片为了待支付订单
         */
        List<String> goodsImages = new ArrayList<>();
        submitOrderVo.getShopOrders().forEach(o -> {
            o.getItems().forEach(c -> {
                goodsImages.add(c.getGoodsCover());
            });
        });


        long expiredTimestamp = saleConfigService.getExpiredTimestamp();
        /**
         * 创建支付订单（1，用来做合单，2用来做支付）
         */
        OrderConstant.PayMode payMode = OrderConstant.PayMode.POINT;
        if(submitOrderVo.getTotalMoney().compareTo(BigDecimal.ZERO)>0)
        {
            payMode = OrderConstant.PayMode.POINT_BALANCE;
        }
        PayOrder payOrder = payOrderService.initPayOrderForSaleAndPoint(userId, submitOrderVo.getTotalMoney(), submitOrderVo.getTotalReduced(),submitOrderVo.getTotalPoint(), payMode, OrderConstant.OrderType.SALE_ORDER, goodsImages, expiredTimestamp,submitOrderVo.getPlatformCoupon(),submitOrderVo.getAreaFeature());

        List<SubmitShopOrderVo> shopOrders = submitOrderVo.getShopOrders();
        for (SubmitShopOrderVo shopOrder : shopOrders) {
            /**
             * 开始创建商家订单
             */
            Order order = createOrder(userId, payOrder, submitOrderVo, shopOrder);

            integralRecordService.outer(order.getUserId(),order.getTotalPoint(),
                    IntegralConstant.OuterMode.CONSUME, IntegralConstant.IntegralModelType.ORDER,order.getId(),
                    String.format("积分兑换订单[%s],扣除积分:%.2f",order.getOrderCode(),order.getTotalPoint()));

            /**
             * 创建收货地址或自提信息
             */
            createOrderReceiving(order, submitOrderVo);
            /**
             * 创建订单的钥匙
             */
            createOrderKey(order);
            List<SubmitChildOrderVo> items = shopOrder.getItems();
            for (SubmitChildOrderVo childOrderVo : items) {
                /**
                 * 创建订单的商品子订单明细
                 */
                childOrderService.create(order, childOrderVo);
            }
        }
        return payOrder;
    }

    @Override
    public void thirdCanSaleCheck(SubmitOrderVo vo) {

    }

    /**
     * 校验普通商品
     *
     * @param userId
     * @param dto
     */
    private void validateGoods(Long userId, SubmitOrderDTO dto) {

        Map<Long, Integer> goodsCountMap = new HashMap<>();
        dto.getShopOrders().forEach(sso -> {
            Map<Long, Integer> goodsMap = sso.getItems().stream().collect(Collectors.groupingBy(SubmitChildOrderDTO::getGoodsId, Collectors.summingInt(SubmitChildOrderDTO::getNum)));
            goodsMap.forEach((key, value) -> {
                if (goodsCountMap.containsKey(key)) {
                    goodsCountMap.put(key, goodsCountMap.get(key) + value);
                } else {
                    goodsCountMap.put(key, value);
                }
            });
        });

        goodsCountMap.forEach((goodsId, buyNum) -> {
            //普通商品限购
            Goods goods = goodsService.getById(goodsId, true);
            if (goods.getLimitBuyNum() > 0) {
                String goodsTitle = StrUtil.truncation(goods.getTitle(), 10);
                if (buyNum > goods.getLimitBuyNum()) {
                    throw new RRException("[" + goodsTitle + "],每人限购" + goods.getLimitBuyNum() + "件",GoodsExceptionEnum.GOODS_LIMIT_BUY.getCode());
                } else {
                    Integer buyGoodsCount = childOrderService.getBuyGoodsCount(userId, goodsId, 0);
                    if (buyGoodsCount + buyNum > goods.getLimitBuyNum()) {
                        throw new RRException("[" + goodsTitle + "],每人限购" + goods.getLimitBuyNum() + "件",GoodsExceptionEnum.GOODS_LIMIT_BUY.getCode());
                    }
                }
            }
        });
    }

    /**
     * 内部调用初始化订单的基础数据================================================
     *
     * @param userId
     * @param dto
     * @return
     */
    @Override
    public SubmitOrderVo initSubmitOrderVo(Long userId, SubmitOrderDTO dto) {
        return createOrderService.initSubmitOrderVo(userId,dto);
    }


    /**
     * 内部调用 重构初始化构造提交商家订单vo
     *
     * @param userId
     * @param dto
     * @param o
     * @return
     */
    @Override
    public SubmitShopOrderVo initBuildSubmitShopOrderVo(Long userId, SubmitOrderDTO dto, SubmitShopOrderDTO o) {
        return createOrderService.initBuildSubmitShopOrderVo(userId,dto,o);
    }

    /**
     * 内部调用 重构初始化构造提交商家子订单vo
     *
     * @param saleEntity
     * @param dto
     * @param o
     * @param s
     * @return
     */
    @Override
    public SubmitChildOrderVo initBuildSubmitChildOrderVo(ISaleEntity saleEntity, SubmitOrderDTO dto, SubmitShopOrderDTO o, SubmitChildOrderDTO s) {
        return createOrderService.initBuildSubmitChildOrderVo(saleEntity,dto,o,s);
    }

    @Override
    public void computeSelectedShopCoupon(Long userId, SubmitShopOrderVo vo, SubmitShopOrderDTO dto) {
        createOrderService.computeSelectedShopCoupon(userId,vo,dto);
    }

    @Override
    public void backStageManagement(GiveBalanceDTO dto) {

    }


    /**
     * 积分订单构单
     *
     * @param userId
     * @param vo
     * @param dto
     * @return
     */
    private List<SubmitShopOrderVo> commonOrderBuild(Long userId, SubmitOrderVo vo, SubmitOrderDTO dto) {
        return dto.getShopOrders().stream().map(o -> {

            SubmitShopOrderVo shopOrderVo = initBuildSubmitShopOrderVo(userId, dto, o);
            //如果是普通订单
            shopOrderVo.setSponsorActivityId(0L);
            shopOrderVo.setActivityId(0L);
            shopOrderVo.setActivityTitle("");
            shopOrderVo.setPointGoods(true);
            shopOrderVo.setExchange(true);


            List<SubmitChildOrderVo> childOrderVoList = o.getItems().stream().map(s -> {
                Goods goods = goodsService.getByShopIdAndId(o.getShopId(), s.getGoodsId());
                SubmitChildOrderVo childOrderVo = initBuildSubmitChildOrderVo(goods, dto, o, s);
                GoodsSku goodsSku = goodsSkuService.loadByGoodsAndSkuHashCode(childOrderVo.getGoodsId(), s.getSkuHashCode());
                if (goodsSku == null) {
                    //如果商品规格不存在,报错
                    throw new RRException(GoodsExceptionEnum.PRODUCT_SKU_NOT_EXISTS);
                }
                ProductSingleGoodsEntity singleGoods = goodsSku.loadSingleGoods();
                if (singleGoods == null) {
                    //库存不存在
                    throw new RRException(GoodsExceptionEnum.SINGLE_GOODS_STOCK_NOT_EXISTS);
                }

                childOrderVo.setAreaFeature(GoodsConstant.AreaFeature.GENERAL);
                childOrderVo.setSkuHashCode(s.getSkuHashCode());
                childOrderVo.setSkuSetName(goodsSku.getSkuSetName());
                childOrderVo.setSkuBarCode(goodsSku.getBarCode());
                if (StringUtils.isNotBlank(goodsSku.getCover())) {
                    childOrderVo.setGoodsCover(goodsSku.getCover());
                }
                childOrderVo.setSingleGoodsId(singleGoods.getId());
                childOrderVo.setSingleGoodsCode(singleGoods.getCode());
                childOrderVo.setSingleGoodsTitle(singleGoods.getTitle());
                childOrderVo.setUnit(singleGoods.getUnit());


                //显示库存的情况=====================================
                if (s.getNum() <= singleGoods.getAbleStock()) {
                    //0库存足够
                    childOrderVo.setStockStatus(0);
                    //2库存紧张
                    if (singleGoods.getAbleStock() < 10) {
                        childOrderVo.setStockStatus(2);
                    }

                } else {
                    //1库存不足
                    childOrderVo.setStockStatus(1);
                }

                //设置重量
                childOrderVo.setWeight(goodsSku.getWeight());
                childOrderVo.setTotalWeight(MathUtils.multiply(new BigDecimal(s.getNum()), goodsSku.getWeight()));
                //设总体积
                childOrderVo.setVolume(goodsSku.getVolume());
                childOrderVo.setTotalVolume(MathUtils.multiply(new BigDecimal(s.getNum()), goodsSku.getVolume()));
                //设总成本
                childOrderVo.setCost(singleGoods.getCostPrice());
                childOrderVo.setTotalCost(MathUtils.multiply(new BigDecimal(s.getNum()), singleGoods.getCostPrice()));
                //首页优惠分摊
                childOrderVo.setFirstOrderReduced(BigDecimal.ZERO);
                //计算会员的折扣积分商品不打折
                //BigDecimal discount = goodsService.getUserGoodsDiscount(userId, goods);

                //设置折扣后的价格
                childOrderVo.setFactPrice(goodsSku.getSalePrice());
                childOrderVo.setSalePrice(goodsSku.getSalePrice());
                childOrderVo.setMarketPrice(goods.getMaxMarketPrice());
                childOrderVo.setTotalReduced(BigDecimal.ZERO);

                childOrderVo.setTotalPrice(MathUtils.multiply(childOrderVo.getFactPrice(), new BigDecimal(s.getNum())));
                childOrderVo.setOriginalGoodsAmount(MathUtils.multiply(childOrderVo.getSalePrice(), new BigDecimal(s.getNum())));


                childOrderVo.setExchangePoint(goodsSku.getExchangePoint());
                childOrderVo.setTotalPoint(MathUtils.multiply(goodsSku.getExchangePoint(),new BigDecimal(s.getNum())));



                return childOrderVo;
            }).collect(Collectors.toList());

            //每家店的订单商品总优惠
           // BigDecimal totalReduced = MathUtils.setScale(childOrderVoList.stream().mapToDouble(c -> c.getTotalReduced().doubleValue()).sum());
            BigDecimal totalReduced = BigDecimal.ZERO;
            //每家店的商品总费用
            BigDecimal totalAmount = MathUtils.setScale(childOrderVoList.stream().mapToDouble(c -> c.getTotalPrice().doubleValue()).sum());
            //设算每家店的商品快递费用
            BigDecimal totalFreight = BigDecimal.ZERO;
            if (dto.getShipmentMode() == 0) {
                if (vo.getReceipt() != null) {
                    totalFreight = processFreight(o.getShopId(), vo.getReceipt(), childOrderVoList);
                }
            }

            shopOrderVo.setItems(childOrderVoList);
            shopOrderVo.setAreaFeature(GoodsConstant.AreaFeature.GENERAL);
            // 首单优惠出来之后这里还要加上首单优惠,同时还要分摊给每个子订单
            BigDecimal firstOrderReduced = BigDecimal.ZERO;
            shopOrderVo.setFirstOrderReduced(firstOrderReduced);
            shopOrderVo.setTotalReduced(MathUtils.add(totalReduced, firstOrderReduced));
            //订单总成本
            shopOrderVo.setTotalCost(MathUtils.setScale(childOrderVoList.stream().mapToDouble(ss -> ss.getTotalCost().doubleValue()).sum()));
            //原商品总价
            shopOrderVo.setOriginalGoodsAmount(MathUtils.setScale(childOrderVoList.stream().mapToDouble(ss -> ss.getOriginalGoodsAmount().doubleValue()).sum()));

            //订单商品总价
            shopOrderVo.setTotalGoodsAmount(totalAmount);
            //订单运费
            shopOrderVo.setTotalFreight(totalFreight);
            //订单总费用(积分订单的总费用只记运费不记商品总价)
            shopOrderVo.setTotalAmount(totalFreight);
            //订单商品总数
            shopOrderVo.setGoodsNum(childOrderVoList.stream().mapToInt(SubmitChildOrderVo::getNum).sum());

            //总积分
            shopOrderVo.setTotalPoint(MathUtils.setScale(childOrderVoList.stream().mapToDouble(c -> c.getTotalPoint().doubleValue()).sum()));
            return shopOrderVo;
        }).collect(Collectors.toList());
    }


    /**
     * 创建订单的钥匙
     *
     * @param order
     */
    @Override
    public void createOrderKey(Order order) {
        createOrderService.createOrderKey(order);
    }

    /**
     * 创建收货地址或自提信息
     *
     * @param order
     * @param vo
     */
    @Override
    public void createOrderReceiving(Order order, SubmitOrderVo vo) {
        createOrderService.createOrderReceiving(order,vo);
    }


    /**
     * 创建订单
     *
     * @param userId
     * @param payOrder
     * @param submitOrderVo
     * @param vo
     * @return
     */
    @Override
    public Order createOrder(Long userId, PayOrder payOrder, SubmitOrderVo submitOrderVo, SubmitShopOrderVo vo) {
        return createOrderService.createOrder(userId,payOrder,submitOrderVo,vo);
    }


    /**
     * 计算一个店铺下的订单的所有商品的运费合计
     *
     * @param shopId
     * @param receipt
     * @param childOrderVoList
     * @return
     */
    @Override
    public BigDecimal processFreight(Long shopId, SubmitOrderReceiptVo receipt, List<SubmitChildOrderVo> childOrderVoList) {
        return createOrderService.processFreight(shopId,receipt,childOrderVoList);
    }


}
